{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The IPython widgets, now in IHaskell !!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is highly recommended that users new to jupyter/ipython take the *User Interface Tour* from the toolbar above (Help -> User Interface Tour)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> This notebook introduces the [IPython widgets](https://github.com/ipython/ipywidgets), as implemented in [IHaskell](https://github.com/gibiansky/IHaskell). The `Button` widget is also demonstrated as a live action example."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Widget Hierarchy\n",
    "\n",
    "These are all the widgets available from IPython/Jupyter."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Uncategorized Widgets\n",
    "\n",
    "+ Button\n",
    "+ Image*Widget*\n",
    "+ Output*Widget*\n",
    "\n",
    "#### Box Widgets\n",
    "\n",
    "+ Box\n",
    "+ FlexBox\n",
    "+ Accordion\n",
    "+ Tab*Widget*\n",
    "\n",
    "#### Boolean Widgets\n",
    "\n",
    "+ CheckBox\n",
    "+ ToggleButton\n",
    "\n",
    "#### Integer Widgets\n",
    "\n",
    "+ IntText\n",
    "+ BoundedIntText\n",
    "+ IntProgress\n",
    "+ IntSlider\n",
    "+ IntRangeSlider\n",
    "\n",
    "#### Float Widgets\n",
    "\n",
    "+ FloatText\n",
    "+ BoundedFloatText\n",
    "+ FloatProgress\n",
    "+ FloatSlider\n",
    "+ FloatRangeSlider\n",
    "\n",
    "#### Selection Widgets\n",
    "\n",
    "+ Selection\n",
    "+ Dropdown\n",
    "+ RadioButtons\n",
    "+ Select\n",
    "+ SelectMultiple\n",
    "+ ToggleButtons\n",
    "\n",
    "#### String Widgets\n",
    "\n",
    "+ HTML*Widget*\n",
    "+ Latex*Widget*\n",
    "+ TextArea\n",
    "+ Text*Widget*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Using Widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Necessary Extensions and Imports\n",
    "\n",
    "All the widgets and related functions are available from a single module, `IHaskell.Display.Widgets`. It is strongly recommended that users use the `OverloadedStrings` extension, as widgets make extensive use of `Text`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "{-# LANGUAGE OverloadedStrings #-}\n",
    "import IHaskell.Display.Widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The module can be imported unqualified. Widgets with common names, such as `Text`, `Image` etc. have a `-Widget` suffix to prevent name collisions."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Widget interface\n",
    "\n",
    "Each widget has different properties, but the surface level API is the same.\n",
    "\n",
    "Every widget has:\n",
    "\n",
    "1. A constructor:\n",
    "    An `IO <widget>` value/function of the form `mk<widget_name>`.\n",
    "2. A set of properties, which can be manipulated using `setField` and `getField`.\n",
    "\n",
    "The `setField` and `getField` functions have nasty type signatures, but they can be used by just intuitively understanding them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    ":t setField"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `setField` function takes three arguments:\n",
    "\n",
    "1. A widget\n",
    "2. A `Field`\n",
    "3. A value for the `Field`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    ":t getField"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `getField` function takes a `Widget` and a `Field` and returns the value of that `Field` for the `Widget`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another utility function is `properties`, which shows all properties of a widget."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    ":t properties"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Displaying Widgets\n",
    "\n",
    "IHaskell automatically displays anything *displayable* given to it directly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "-- Showables\n",
    "1 + 2\n",
    "\"abc\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Widgets can either be displayed this way, or explicitly using the `display` function from `IHaskell.Display`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import IHaskell.Display\n",
    ":t display"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Multiple displays\n",
    "\n",
    "A widget can be displayed multiple times. All these *views* are representations of a single object, and thus are linked.\n",
    "\n",
    "When a widget is created, a model representing it is created in the frontend. This model is used by all the views, and any modification to it propagates to all of them."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Closing widgets\n",
    "\n",
    "Widgets can be closed using the `closeWidget` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    ":t closeWidget"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Our first widget: `Button`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's play with buttons as a starting example:\n",
    "\n",
    "As noted before, all widgets have a constructor of the form `mk<Widget>`. Thus, to create a `Button`, we use `mkButton`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "button <- mkButton     -- Construct a Button\n",
    ":t button"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Widgets can be displayed by just entering them into a cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "button                 -- Display the button"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To view a widget's properties, we use the `properties` function. It also shows the type represented by the `Field`, which generally are not visible in type signatures due to high levels of type-hackery."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "-- The button widget has many properties.\n",
    "properties button"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's try making the button widget wider."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "-- 250 pixels wide\n",
    "setField button Width 250"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There is a lot that can be customized. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "setField button Description \"Click Me (._.\\\")\"\n",
    "setField button ButtonStyle SuccessButton\n",
    "setField button BorderStyle RidgeBorder\n",
    "setField button BorderWidth 20\n",
    "setField button BorderRadius 30\n",
    "setField button Padding 10\n",
    "setField button Height 125\n",
    "setField button FontFamily \"cursive\"\n",
    "setField button FontSize 30"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The button widget also provides a click handler. We can make it do anything, except console input. Universally, no widget event can trigger console input."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "setField button ClickHandler $ putStrLn \"fO_o\"\n",
    "button -- Displaying again for convenience"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now try clicking the button, and see the output. If we try to do console input, an error occurs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "setField button ClickHandler $ getLine >>= putStrLn"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "name": "haskell",
   "version": "7.10.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
